package mroute

import (
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"mygo/mymongo"
	"mygo/mystruct"
	"path/filepath"
	"os"
	"fmt"
	"time"
	"strings"
	"strconv"
	"encoding/json"
	"mygo/myws"
	"mygo/mylog"
	"mygo/global"
	"mygo/mroute/utils"
)

/* =================================================================================
   表接口
*/
// 单条数据查询 [非权限认证]
func Mychake(cont *gin.Context) {
	_id := cont.Query("_id")
	apiid := cont.Query("code")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	ret, res := mymongo.Wacth_One(_id, codb)
	if ret.Code == 1 {
		cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": res})
	}else{
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "_id不存在"})
	}
}
// 添加
func MyAppend(cont *gin.Context) {
	apiid := cont.PostForm("code")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	make_map, make_key := utils.User_data_struct(cont, codb.Body, true)
	ret := mymongo.Append_One(make_map, codb)
	if ret.Code == 1 && strings.Contains(cont.Request.Header.Get("Content-Type"), "multipart/form-data") {
		path := filepath.Join(global.Mtoken.Download_Path, codb.Body.Apiid, ret.Mesg)
		if mystruct.Exists(path) == false {
			os.MkdirAll(path, os.ModePerm)
		}
		for key, value := range make_key {
			m_path := filepath.Join(path, key)
			if mystruct.Exists(m_path) == false {
				os.Mkdir(m_path, os.ModePerm)
			}
			cont.SaveUploadedFile(value, filepath.Join(m_path, value.Filename))
    	}
	}
	make_map["_id"] = ret.Mesg
	make_map["apiid"] = apiid
	json_data, _ := json.Marshal(make_map)
	mesg := myws.Mesg{
		Type: "Append",
		Code: ret.Code,
		Api: "/api/append",
		Msg: ret.Mesg,
		Data: json_data,
	}
	go myws.SendWs(mesg)
	mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
	cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})
}
// 批量添加
func MyAppendAll(cont *gin.Context) {
	apiid := cont.PostForm("code")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	value := cont.PostForm("value")
	var json_data []map[string]interface{}
	json.Unmarshal([]byte(value), &json_data)
	var make_map []interface{}
	for _, v := range json_data {
		map_app := make(map[string]interface{})
		for _, _v := range codb.Body.Data {
			switch _v.Select {
				case "string":
					map_app[_v.Value] = v[_v.Value].(string)
				case "file":
					map_app[_v.Value] = ""
				case "int":
					map_app[_v.Value] = int64(v[_v.Value].(float64))
				case "bool":
					map_app[_v.Value] = v[_v.Value].(bool)
				case "prgs":
					map_app[_v.Value] = int64(v[_v.Value].(float64))
				case "word":
					words, _ := v[_v.Value].(map[string]interface{})
					map_app[_v.Value] = map[string]string{"name": words["name"].(string), "id": uuid.New().String(), "model": words["model"].(string)}
				default:
					map_app[_v.Value] = v[_v.Value].(string)
			}
		}
		make_map = append(make_map, mystruct.Map_data{map_app, time.Now()})
	}
	ret := mymongo.Append_All(make_map, codb)
	cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})
	json_customData, _ := json.Marshal(codb.Body)
	mesg := myws.Mesg{
		Type: "AppendAll",
		Api: "/api/appendall",
		Data: json_customData,
	}
	mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
}
// 更新
func MyUpdate(cont *gin.Context) {
	apiid := cont.PostForm("code")
	_id := cont.PostForm("_id")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	make_map, make_key := utils.User_data_struct(cont, codb.Body, false)
	ret := mymongo.Update_One(make_map, codb, _id)
	if ret.Code == 1 && strings.Contains(cont.Request.Header.Get("Content-Type"), "multipart/form-data") {
		path := filepath.Join(global.Mtoken.Download_Path, codb.Body.Apiid, _id)
		if mystruct.Exists(path) == false {
			os.MkdirAll(path, os.ModePerm)
		}
		for key, value := range make_key {
        	m_path := filepath.Join(global.Mtoken.Download_Path, codb.Body.Apiid, _id, key)
			if mystruct.Exists(m_path) == false {
				os.Mkdir(m_path, os.ModePerm)
			}
			cont.SaveUploadedFile(value, filepath.Join(m_path, value.Filename))
    	}
	}
	make_map["apiid"] = apiid
	make_map["_id"] = _id
	json_data, _ := json.Marshal(make_map)
	mesg := myws.Mesg{
		Type: "Update",
		Code: ret.Code,
		Api: "/api/update",
		Msg: ret.Mesg,
		Data: json_data,
	}
	go myws.SendWs(mesg)
	mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
	cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})
}
// 修改某个字段
func MyUpField(cont *gin.Context) {
	field := cont.Query("field")
	apiid := cont.Query("code")
	_id   := cont.Query("_id")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	var valus interface{}
	value := mystruct.FindItemsByName(codb.Body.Data, field)
	if value.Select != "" {
		switch value.Select {
			case "string":
				valus = cont.Query("value")
			case "int":
				valus, _ = strconv.ParseInt(cont.Query("value"), 10, 64)
			case "bool":
				valus, _ = strconv.ParseBool(cont.Query("value"))
			case "tag":
				valus = cont.Query("value")
			case "prgs":
				valus, _ = strconv.ParseInt(cont.Query("value"), 10, 64)
			case "file":
				valus = cont.Query("value")
			case "but":
				valus = cont.Query("value")
			case "pack":
				valus = cont.Query("value")
			case "word":
				valus = cont.Query("value")
				field = fmt.Sprintf("%s.name", field)
		}
	}
	if valus == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "获取修改值失败"})
		return
	}
	ret := mymongo.Update_Field(field, valus, codb, _id)
	make_map := make(map[string]interface{})
	make_map["apiid"] = apiid
	make_map["_id"] = _id
	make_map["field"] = field
	make_map["value"] = valus
	json_data, _ := json.Marshal(make_map)
	mesg := myws.Mesg{
		Type: "Upfield",
		Code: ret.Code,
		Api: "/api/upfield",
		Msg: ret.Mesg,
		Data: json_data,
	}
	go myws.SendWs(mesg)
	mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
	cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})
}
// 删除
func MyDelete(cont *gin.Context) {
	switch cont.Request.Method {
		case "POST":
			apiid := cont.PostForm("code")
			_id   := cont.PostForm("_id")
			codb  := mymongo.Get_Code(apiid)
			if codb == nil {
				cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
				return
			}
			ret := mymongo.Delete_One(_id, codb)
			if ret.Code == 1 {
				path := filepath.Join(global.Mtoken.Download_Path, codb.Body.Apiid, _id)
				if mystruct.Exists(path) {
					os.RemoveAll(path)
				}
				mymongo.MyMonDB.DanmakuCur.Danmaku_Del(fmt.Sprintf("%s_%s", codb.Body.Apiid, _id))
			}
			json_data, _ := json.Marshal(map[string]string{
				"apiid": apiid,
				"_id": _id,
			})
			mesg := myws.Mesg{
				Type: "Delete",
				Code: ret.Code,
				Api: "/api/delete",
				Msg: ret.Mesg,
				Data: json_data,
			}
			go myws.SendWs(mesg)
			mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
			cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})

		case "GET":
			apiid := cont.Query("code")
			_id   := cont.Query("_id")
			codb  := mymongo.Get_Code(apiid)
			if codb == nil {
				cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
				return
			}
			ret := mymongo.Delete_One(_id, codb)
			if ret.Code == 1 {
				path := filepath.Join(global.Mtoken.Download_Path, codb.Body.Apiid, _id)
				if mystruct.Exists(path) {
					os.RemoveAll(path)
				}
			}
			json_data, _ := json.Marshal(map[string]string{
				"apiid": apiid,
				"_id": _id,
			})
			mesg := myws.Mesg{
				Type: "Delete",
				Code: ret.Code,
				Api: "/api/delete",
				Msg: ret.Mesg,
				Data: json_data,
			}
			go myws.SendWs(mesg)
			mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
			cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})

		default:
			cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "请求方式错误"})
	}
}
// 批量删除
func MyDeleteAll(cont *gin.Context) {
	apiid := cont.PostForm("code")
	codb := mymongo.Get_Code(apiid)
	if codb == nil {
		cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
		return
	}
	make_map, _ := utils.User_data_struct(cont, codb.Body, false)
	for key, value := range make_map {
		if value == "" {
			delete(make_map, key)
		}
	}
	ret := mymongo.Delete_All(make_map, codb)
	cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret.Mesg})
	// 日志记录
	json_data, _ := json.Marshal(codb.Body)
	mesg := myws.Mesg{
		Type: "AppendAll",
		Api: "/api/appendall",
		Data: json_data,
	}
	mylog.MyLog(mesg, cont.Request.RemoteAddr, global.Mtoken.Log_Path)
}
// 查询
func MyWacth(cont *gin.Context) {
	make_map := make(map[string]interface{})
	switch cont.Request.Method {
		case "POST":
			codb := mymongo.Get_Code(cont.PostForm("code"))
			if codb == nil {
				cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
				return
			}
			for _, value := range codb.Body.Data {
				switch value.Select {
					case "int":
						intvalue, err := strconv.ParseInt(cont.PostForm(value.Value), 10, 64)
						if err == nil {
							make_map[value.Value] = intvalue
						}
					case "bool":
						bolvalue, err := strconv.ParseBool(cont.PostForm(value.Value))
						if err == nil {
							make_map[value.Value] = bolvalue
						}
					case "prgs":
						prsvalue, err := strconv.ParseInt(cont.PostForm(value.Value), 10, 64)
						if err == nil {
							make_map[value.Value] = prsvalue
						}
					default:
						make_map[value.Value] = cont.PostForm(value.Value)
				}
			}
			make_map["start_time"] = cont.DefaultPostForm("start_time","")
			make_map["stop_time"]  = cont.DefaultPostForm("stop_time","")
			make_map["_id"]  = cont.DefaultPostForm("_id","")
			var limt = &mystruct.Mypage{
				Limit: mystruct.StrToInt64(cont.DefaultPostForm("limit","0")),
				Page: mystruct.StrToInt64(cont.DefaultPostForm("page","0")),
			}
			if limt.Limit != 0 {
				ret, ret_data := mymongo.Wacth_All(make_map, limt, codb)
				cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret_data})
				return
			}
			ret, ret_data := mymongo.Wacth_Sum(make_map, codb)
			cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret_data})

		case "GET":
			codb := mymongo.Get_Code(cont.Query("code"))
        	if codb == nil {
				cont.JSON(mystruct.StatusOK, gin.H{"code": mystruct.MyCodeErr, "msg": "标识不存在"})
				return
			}
			for _, value := range codb.Body.Data {
				switch value.Select {
					case "int":
						intvalue, err := strconv.ParseInt(cont.Query(value.Value), 10, 64)
						if err == nil {
							make_map[value.Value] = intvalue
						}
					case "bool":
						bolvalue, err := strconv.ParseBool(cont.Query(value.Value))
						if err == nil {
							make_map[value.Value] = bolvalue
						}
					case "prgs":
						prsvalue, err := strconv.ParseInt(cont.Query(value.Value), 10, 64)
						if err == nil {
							make_map[value.Value] = prsvalue
						}
					default:
						make_map[value.Value] = cont.Query(value.Value)
				}
			}
			make_map["start_time"] = cont.DefaultQuery("start_time","")
			make_map["stop_time"]  = cont.DefaultQuery("stop_time","")
			make_map["_id"]  = cont.DefaultQuery("_id","")
			var limt = &mystruct.Mypage{
				Limit: mystruct.StrToInt64(cont.DefaultQuery("limit","0")),
				Page: mystruct.StrToInt64(cont.DefaultQuery("page","0")),
			}
			if limt.Limit != 0 {
				ret, ret_data := mymongo.Wacth_All(make_map, limt, codb)
				cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret_data})
				return
			}
			ret, ret_data := mymongo.Wacth_Sum(make_map, codb)
			cont.JSON(mystruct.StatusOK, gin.H{"code": ret.Code, "msg": ret_data})
	}
}